package com.chenc.javathreads.controlleraop.intercetor;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.chenc.javathreads.common.NormalInteceptorEnum;
import com.chenc.javathreads.controlleraop.config.RequestWrapper;
import com.chenc.javathreads.controlleraop.dto.InterfaceLogDto;
import com.chenc.javathreads.controlleraop.service.OperationLogService;
import com.chenc.javathreads.util.RequestIp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.NamedThreadLocal;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.Map;

/**
 * @ClassName
 * @Describtion:  线程不安全 想办法线程安全
 * @Author:Chenc
 * @Date:2023/12/18 14:59
 * @Version 1.0
 */
@Component
public class LogInterceptor implements HandlerInterceptor {

    private NamedThreadLocal<InterfaceLogDto> threadLocal = new NamedThreadLocal<>("threadLocal");

    @Autowired
    OperationLogService operationLogService;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
//        Enumeration<String> attributeNames = request.getAttributeNames();
//        StringBuilder stringBuilder = new StringBuilder();
//        while (true){
//            if (attributeNames.hasMoreElements()){
//                String attributeName = attributeNames.nextElement();
//                Object attributeValue = request.getAttribute(attributeName);
//                stringBuilder.append("attributeName:").append(attributeName).append(",attributeValue:").append(attributeValue).append("\n\r");
//            }else {
//                break;
//            }
//        }
//        System.out.println(stringBuilder.toString());
        InterfaceLogDto interfaceLogDto = new InterfaceLogDto();
        interfaceLogDto.setRequestMethod(request.getMethod());
        interfaceLogDto.setRequestUrl(request.getRequestURI());
        interfaceLogDto.setIp(RequestIp.getIPAddress(request));
        Thread thread = Thread.currentThread();
        interfaceLogDto.setThreadName(thread.getName());
        interfaceLogDto.setStartTime(new Date());
        interfaceLogDto.setGobaleSerialNo(String.valueOf(request.getAttribute(NormalInteceptorEnum.GOLBAL_NO.getValue())));
//        private String gobaleSerialNo;//全局流水号
        if ("GET".equals(request.getMethod())){
            Object attribute = request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
            if (null != attribute){
                Map convert = Convert.convert(Map.class, attribute);
                interfaceLogDto.setParamJson(JSONUtil.toJsonStr(convert));
            }
        }
        try{
            String jsonParam = new RequestWrapper(request).getBodyString();
            if (JSONUtil.isJson(jsonParam)){
                interfaceLogDto.setParamJson(jsonParam);
            }
        }catch(Exception e){

        }
        threadLocal.set(interfaceLogDto);

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {


    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws IOException {
        int status = response.getStatus();
        Object resBody = request.getAttribute(NormalInteceptorEnum.RESPONSE_BODY.getValue());
        InterfaceLogDto interfaceLogDto = threadLocal.get();
        Date endtime = new Date();
        Long betweenMs = DateUtil.betweenMs(interfaceLogDto.getStartTime(), endtime);
        interfaceLogDto.setEndTime(endtime);
        interfaceLogDto.setResultCode(String.valueOf(status));
        interfaceLogDto.setResultJson(null == resBody?"":resBody.toString());
        interfaceLogDto.setSpendTime(betweenMs);
        operationLogService.save(interfaceLogDto);
    }

    /**
     * 判断本次请求的数据类型是否为json
     *
     * @param request request
     * @return boolean
     */
    private boolean isJson(HttpServletRequest request) {
        if (request.getContentType() != null) {
            return request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE) ||
                    request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE);
        }

        return false;
    }

}
